/**
 * @copyright Copyright (c) 2007-2024, Guangzhou Xaircraft Technology Co., Ltd.
 */
#ifndef PROCESS_MONITOR_H_  // NOLINT
#define PROCESS_MONITOR_H_

#include <time.h>
#include <sched.h> /* For __CPU_SETSIZE */
#include <limits.h>
#include <stdlib.h>
#include <list>
#include <map>
#include <string>
#include <stdint.h>  // NOLINT
#include <unordered_map>
#include <vector>

#include "BasicExcel.hpp"     // NOLINT
// #include "application/application.h"
#include "Common.h"  // NOLINT
// #include "linux/linux_util.h"
// #include "deamon/cgroup_manager.h"
// #include "deamon/cpu_affinity.h"

namespace xag {  // NOLINT
  namespace xos {  // NOLINT
    namespace deamon {  // NOLINT
      struct SysMonitorStats {  // NOLINT
        std::string ts;
      };

      struct MonitorInfo {  // NOLINT
        bool exits;
        SysMonitorStats sys_stats[2];
        std::map<pid_t, st_pid> all_process_map;
      };

      struct ExcelTool {  // NOLINT
        YExcel::BasicExcel excel;
        std::string excel_name;
      };

      struct SysCpuState {  // NOLINT
        double cpu_utilization;
        double cpu_temperature;
        double user;
        double nice;
        double system;
        double idle;
        double iowait;
        double irq;
        double softirq;
        double ctxt;
        double intr;
        double blocked;
      };

      struct CpuInfo_t {  // NOLINT
        char name[32];
        int user;
        int nice;
        int system;
        int idle;
        int iowait;
        int irq;
        int softirq;
        long ctxt;  // NOLINT
        long intr;  // NOLINT
        long blocked;  // NOLINT
        uint64_t uptime_cs;
      };

      struct Memory_t {  // NOLINT
        char name[32];
        long total;  // NOLINT
        char name2[32];
        long free;  // NOLINT
        char name3[32];
        long available;  // NOLINT
      };

      enum ExcelWorkType {
        IDLE = 0,
        WORKING = 1,
      };

      class MonitorReport {  // NOLINT
      public:  // NOLINT
        MonitorReport();
        ~MonitorReport();

        void init();

        void set_pid_stat(const st_pid &pid_stat, uint32_t get_curr, uint64_t now_time);
        void update(uint64_t now_time);
        void sync_work_type(void);

      private:  // NOLINT
        void save_excel(int prev,
                        int curr,
                        uint64_t itv);

      private:  // NOLINT
        static std::vector<const char *> sheet_title;
        static std::vector<const char *> sheet_sys_title;
        bool report_switch = false;
        int32_t record_duration_min = 5;
        int32_t record_max_sheet_cnt = 10;
        int32_t record_interval_time_sec = 60;

        MonitorInfo monitor_info;
        uint64_t uptime_cs[2] = {0, 0};
        uint32_t curr = 1;
        ExcelTool excel_tool[2];

        ExcelWorkType work_type = ExcelWorkType::IDLE;
        ExcelWorkType get_work_type = ExcelWorkType::IDLE;
        // std::shared_ptr<xag_nav::os::StorageBase> storage_;
        CpuInfo_t cpu_info_last;
      };

      class ProcessMonitor {  // NOLINT
      public:  // NOLINT
        ProcessMonitor();
        ~ProcessMonitor();

        void init();
        // void init(bool cgroup_switch,const rapidjson::Document& config_document);
        void loop(bool print_info);
        std::vector<ProgramState> get_program_state_vector(void);

      private:  // NOLINT
        st_pid *add_list_pid(pid_t pid, pid_t tgid);
        bool read_stats(int curr);
        void sfree_pids(bool force);
        bool read_proc_pid_stat(pid_t pid,
                                st_pid *plist,
                                uint32_t *thread_nr,
                                pid_t tgid,
                                int curr);
        bool read_pid_stats(pid_t pid,
                            st_pid *plist,
                            uint32_t *thread_nr,
                            pid_t tgid,
                            int curr);
        bool read_proc_pid_sched(pid_t pid, st_pid *plist, pid_t tgid, int curr);
        bool read_proc_pid_status(pid_t pid, st_pid *plist, pid_t tgid, int curr);
        bool read_proc_pid_io(pid_t pid, st_pid *plist, pid_t tgid, int curr);
        void read_task_stats(pid_t pid, st_pid *plist, int curr);
        int write_stats_core(int prev, int curr);
        int write_stats(int curr);
        int write_pid_task_all_stats(int prev, int curr, uint64_t itv);
        void set_pid_nonexistent(void);

      private:  // NOLINT
        std::unordered_map<pid_t, st_pid> all_process_map;
        std::vector<ProgramState> program_state_vector;  // NOLINT
        uint64_t uptime_cs[2] = {0, 0};
        uint32_t curr = 1;
        MonitorReport monitor_report;
        // CgroupManager cgroup_manager_;
        // CpuAffinity cpu_affinity_;
        uint64_t io_uptime_cs[2] = {0, 0};
        uint64_t io_read_cnt_ = 0;
        uint32_t io_curr = 0;
      };

    }  // NOLINT
  }  // NOLINT
}  // NOLINT

#endif  // PROCESS_MONITOR_H_  // NOLINT
